package com.llu.thread;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;

public class FutureTaskTest {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        // 计算开始时间
        long startTime = System.currentTimeMillis();
        Long res = 0L;
        for (int i = 1; i <= 5; i++) {
            res += getNFactorial(i).get(i);
        }
        System.out.println("res :  " + res );
        System.out.println("普通计算计算时间（ms）：" + (System.currentTimeMillis() - startTime));

        // 使用FutureTask
        startTime = System.currentTimeMillis();
        /**
         * corePoolSize: 2
         * maximumPoolSize: 4
         * keepAliveTime: 1s
         * workQueue: 容量为 4 的 LinkedBlockingQueue
         * threadFactory: 默认的 DefaultThreadFactory
         * handler: 默认的 AbortPolicy，抛异常
         */
        ThreadPoolExecutor threadPoolExecutor
                = new ThreadPoolExecutor(
                10
                , 15
                , 5
                , TimeUnit.SECONDS
                , new LinkedBlockingQueue<>(4)
                // , (r, t) -> System.out.println("reject handle")
        );
        // 创建FutureTask的列表来存储每个任务
        List<FutureTask<Map<Integer, Long>>> futureTasks = new ArrayList<>();

        for (int i = 1; i <= 5; i++) {
            // 常见FutureTask
            int finalI = i;
            FutureTask<Map<Integer, Long>> mapFutureTask = new FutureTask<Map<Integer, Long>>(
                    () -> {
                        return getNFactorial(finalI);
                    }
            );
            futureTasks.add(mapFutureTask);

            // 提交 FutureTask 到线程池
            threadPoolExecutor.submit(mapFutureTask);
        }
        // 组装数据
        AtomicReference<Long> res2 = new AtomicReference<>(0L);
        for (FutureTask<Map<Integer, Long>> futureTask : futureTasks) {
            Map<Integer, Long> integerLongMap = futureTask.get();
            integerLongMap.forEach(
                    (k, v) -> {
                        res2.updateAndGet(v1 -> v1 + v);
                        System.out.println(k + " : " + v);
                    }
            );
        }

        System.out.println( "res2 : " + res2);
        // 计算结束时间
        System.out.println("多线程计算计算时间（ms）：" + (System.currentTimeMillis() - startTime));

        // 关闭线程池
        threadPoolExecutor.shutdown();

    }


    // 计算 n 的阶乘
    public static Map<Integer, Long> getNFactorial(int n) throws InterruptedException {
        Thread.sleep(1000);
        long res = 1 ;
        for (int i = 1; i <= n; i++) {
            res = res * i;
        }
        HashMap<Integer,Long> hashMap = new HashMap<Integer,Long>();
        hashMap.put(n,res);
        return  hashMap;
    }






    public static void testFutureTask(){
        /**
         * 这段代码的功能是创建一个 ExecutorService 实例，使用 Executors.newCachedThreadPool() 方法。具体来说：
         * ExecutorService：这是一个接口，提供了管理异步任务执行的方法。
         * Executors.newCachedThreadPool()：这是一个工厂方法，用于创建一个线程池。这个线程池会根据需要创建新线程，
         * 但在先前构建的线程可用时将重用它们。适用于执行大量短期异步任务。
         */
        ExecutorService executorService = Executors.newCachedThreadPool();


        FutureTask<Integer> futureTask = new FutureTask<Integer>(new Task());

        //  新建Thread对象并启动
        Thread thread = new Thread(futureTask);
        thread.setName("Task thread");
        thread.start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Thread [" + Thread.currentThread().getName() + "] is running");

        // 4. 调用isDone()判断任务是否结束
        if(!futureTask.isDone()) {
            System.out.println("Task is not done");
        }

        int result = 0;

        try {
            // 5. 调用get()方法获取任务结果,如果任务没有执行完成则阻塞等待
            result = futureTask.get();
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("result is " + result);
    }
    // 1. 继承Callable接口,实现call()方法,泛型参数为要返回的类型
    static class Task  implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            System.out.println("Thread [" + Thread.currentThread().getName() + "] is running");
            int result = 0;
            for(int i = 0; i < 1000000000;++i) {
                result += i;
            }

            Thread.sleep(5000);
            return result;
        }
    }

}
